Trò chơi Angry Birds trong UNITY Engine
31.649 lượt xem;
1 // spline equation courtesy Andeeee's CRSpline (http://forum.unity3d.com/threads/32954-Waypoints-and-constant-variable-speed-problems?p=213942&viewfull=1#post213942)
2
3 using UnityEngine;
4 using System.IO;
5 using System.Collections;
6 using System.Collections.Generic;
7
8
9 public class GoSpline
10 {
11 public int currentSegment { get; private set; }
12 public bool isClosed { get; private set; }
13 public GoSplineType splineType { get; private set; }
14
15 // used by the visual path editor
16 public List<Vector3> nodes { get { return _solver.nodes; } }
17
18 private bool _isReversed; // internal flag that lets us know if our nodes are reversed or not
19 private AbstractGoSplineSolver _solver;
20
21
22 // default constructor
23 public GoSpline( List<Vector3> nodes, bool useStraightLines = false )
24 {
25 // determine spline type and solver based on number of nodes
26 if( useStraightLines || nodes.Count == 2 )
27 {
28 splineType = GoSplineType.StraightLine;
29 _solver = new GoSplineStraightLineSolver( nodes );
30 }
31 else if( nodes.Count == 3 )
32 {
33 splineType = GoSplineType.QuadraticBezier;
34 _solver = new GoSplineQuadraticBezierSolver( nodes );
35 }
36 else if( nodes.Count == 4 )
37 {
38 splineType = GoSplineType.CubicBezier;
39 _solver = new GoSplineCubicBezierSolver( nodes );
40 }
41 else
42 {
43 splineType = GoSplineType.CatmullRom;
44 _solver = new GoSplineCatmullRomSolver( nodes );
45 }
46 }
47
48
49 public GoSpline( Vector3[] nodes, bool useStraightLines = false ) : this( new List<Vector3>( nodes ), useStraightLines )
50 {}
51
52
53 public GoSpline( string pathAssetName, bool useStraightLines = false ) : this( nodeListFromAsset( pathAssetName ), useStraightLines )
54 {}
55
56
57 /// <summary>
58 /// helper to get a node list from an asset created with the visual editor
59 /// </summary>
60 private static List<Vector3> nodeListFromAsset( string pathAssetName )
61 {
62 if( Application.platform == RuntimePlatform.OSXWebPlayer || Application.platform == RuntimePlatform.WindowsWebPlayer )
63 {
64 Debug.LogError( "The Web Player does not support loading files from disk." );
65 return null;
66 }
67
68
69 var path = string.Empty;
70 if( !pathAssetName.EndsWith( ".asset" ) )
71 pathAssetName += ".asset";
72
73
74 if( Application.platform == RuntimePlatform.Android )
75 {
76 path = Path.Combine( "jar:file://" + Application.dataPath + "!/assets/", pathAssetName );
77
78 WWW loadAsset = new WWW( path );
79 while( !loadAsset.isDone ) { } // maybe make a safety check here
80
81 return bytesToVector3List( loadAsset.bytes );
82 }
83 else if( Application.platform == RuntimePlatform.IPhonePlayer )
84 {
85 // at runtime on iOS, we load from the dataPath
86 path = Path.Combine( Path.Combine( Application.dataPath, "Raw" ), pathAssetName );
87 }
88 else
89 {
90 // in the editor we default to looking in the StreamingAssets folder
91 path = Path.Combine( Path.Combine( Application.dataPath, "StreamingAssets" ), pathAssetName );
92 }
93
94 #if UNITY_WEBPLAYER || NETFX_CORE || UNITY_WINRT
95 // it isnt possible to get here but the compiler needs it to be here anyway
96 return null;
97 #else
98 var bytes = File.ReadAllBytes( path );
99 return bytesToVector3List( bytes );
100 #endif
101 }
102
103
104 /// <summary>
105 /// helper to get a node list from an asset created with the visual editor
106 /// </summary>
107 public static List<Vector3> bytesToVector3List( byte[] bytes )
108 {
109 var vecs = new List<Vector3>();
110 for( var i = 0; i < bytes.Length; i += 12 )
111 {
112 var newVec = new Vector3( System.BitConverter.ToSingle( bytes, i ), System.BitConverter.ToSingle( bytes, i + 4 ), System.BitConverter.ToSingle( bytes, i + 8 ) );
113 vecs.Add( newVec );
114 }
115
116 return vecs;
117 }
118
119
120 /// <summary>
121 /// gets the last node. used to setup relative tweens
122 /// </summary>
123 public Vector3 getLastNode()
124 {
125 return _solver.nodes[_solver.nodes.Count];
126 }
127
128
129 /// <summary>
130 /// responsible for calculating total length, segmentStartLocations and segmentDistances
131 /// </summary>
132 public void buildPath()
133 {
134 _solver.buildPath();
135 }
136
137
138 /// <summary>
139 /// directly gets the point for the current spline type with no lookup table to adjust for constant speed
140 /// </summary>
141 private Vector3 getPoint( float t )
142 {
143 return _solver.getPoint( t );
144 }
145
146
147 /// <summary>
148 /// returns the point that corresponds to the given t where t >= 0 and t <= 1 making sure that the
149 /// path is traversed at a constant speed.
150 /// </summary>
151 public Vector3 getPointOnPath( float t )
152 {
153 // if the path is closed, we will allow t to wrap. if is not we need to clamp t
154 if( t < 0 || t > 1 )
155 {
156 if( isClosed )
157 {
158 if( t < 0 )
159 t += 1;
160 else
161 t -= 1;
162 }
163 else
164 {
165 t = Mathf.Clamp01( t );
166 }
167 }
168
169 return _solver.getPointOnPath( t );
170 }
171
172
173 /// <summary>
174 /// closes the path adding a new node at the end that is equal to the start node if it isn't already equal
175 /// </summary>
176 public void closePath()
177 {
178 // dont let this get closed twice!
179 if( isClosed )
180 return;
181
182 isClosed = true;
183 _solver.closePath();
184 }
185
186
187 /// <summary>
188 /// reverses the order of the nodes
189 /// </summary>
190 public void reverseNodes()
191 {
192 if( !_isReversed )
193 {
194 _solver.reverseNodes();
195 _isReversed = true;
196 }
197 }
198
199
200 /// <summary>
201 /// unreverses the order of the nodes if they were reversed
202 /// </summary>
203 public void unreverseNodes()
204 {
205 if( _isReversed )
206 {
207 _solver.reverseNodes();
208 _isReversed = false;
209 }
210 }
211
212
213 public void drawGizmos( float resolution )
214 {
215 _solver.drawGizmos();
216
217 var previousPoint = _solver.getPoint( 0 );
218
219 resolution *= _solver.nodes.Count;
220 for( var i = 1; i <= resolution; i++ )
221 {
222 var t = (float)i / resolution;
223 var currentPoint = _solver.getPoint( t );
224 Gizmos.DrawLine( currentPoint, previousPoint );
225 previousPoint = currentPoint;
226 }
227 }
228
229
230 /// <summary>
231 /// helper for drawing gizmos in the editor
232 /// </summary>
233 public static void drawGizmos( Vector3[] path, float resolution = 50 )
234 {
235 // horribly inefficient but it only runs in the editor
236 var spline = new GoSpline( path );
237 spline.drawGizmos( resolution );
238 }
239
240 }
2
3 using UnityEngine;
4 using System.IO;
5 using System.Collections;
6 using System.Collections.Generic;
7
8
9 public class GoSpline
10 {
11 public int currentSegment { get; private set; }
12 public bool isClosed { get; private set; }
13 public GoSplineType splineType { get; private set; }
14
15 // used by the visual path editor
16 public List<Vector3> nodes { get { return _solver.nodes; } }
17
18 private bool _isReversed; // internal flag that lets us know if our nodes are reversed or not
19 private AbstractGoSplineSolver _solver;
20
21
22 // default constructor
23 public GoSpline( List<Vector3> nodes, bool useStraightLines = false )
24 {
25 // determine spline type and solver based on number of nodes
26 if( useStraightLines || nodes.Count == 2 )
27 {
28 splineType = GoSplineType.StraightLine;
29 _solver = new GoSplineStraightLineSolver( nodes );
30 }
31 else if( nodes.Count == 3 )
32 {
33 splineType = GoSplineType.QuadraticBezier;
34 _solver = new GoSplineQuadraticBezierSolver( nodes );
35 }
36 else if( nodes.Count == 4 )
37 {
38 splineType = GoSplineType.CubicBezier;
39 _solver = new GoSplineCubicBezierSolver( nodes );
40 }
41 else
42 {
43 splineType = GoSplineType.CatmullRom;
44 _solver = new GoSplineCatmullRomSolver( nodes );
45 }
46 }
47
48
49 public GoSpline( Vector3[] nodes, bool useStraightLines = false ) : this( new List<Vector3>( nodes ), useStraightLines )
50 {}
51
52
53 public GoSpline( string pathAssetName, bool useStraightLines = false ) : this( nodeListFromAsset( pathAssetName ), useStraightLines )
54 {}
55
56
57 /// <summary>
58 /// helper to get a node list from an asset created with the visual editor
59 /// </summary>
60 private static List<Vector3> nodeListFromAsset( string pathAssetName )
61 {
62 if( Application.platform == RuntimePlatform.OSXWebPlayer || Application.platform == RuntimePlatform.WindowsWebPlayer )
63 {
64 Debug.LogError( "The Web Player does not support loading files from disk." );
65 return null;
66 }
67
68
69 var path = string.Empty;
70 if( !pathAssetName.EndsWith( ".asset" ) )
71 pathAssetName += ".asset";
72
73
74 if( Application.platform == RuntimePlatform.Android )
75 {
76 path = Path.Combine( "jar:file://" + Application.dataPath + "!/assets/", pathAssetName );
77
78 WWW loadAsset = new WWW( path );
79 while( !loadAsset.isDone ) { } // maybe make a safety check here
80
81 return bytesToVector3List( loadAsset.bytes );
82 }
83 else if( Application.platform == RuntimePlatform.IPhonePlayer )
84 {
85 // at runtime on iOS, we load from the dataPath
86 path = Path.Combine( Path.Combine( Application.dataPath, "Raw" ), pathAssetName );
87 }
88 else
89 {
90 // in the editor we default to looking in the StreamingAssets folder
91 path = Path.Combine( Path.Combine( Application.dataPath, "StreamingAssets" ), pathAssetName );
92 }
93
94 #if UNITY_WEBPLAYER || NETFX_CORE || UNITY_WINRT
95 // it isnt possible to get here but the compiler needs it to be here anyway
96 return null;
97 #else
98 var bytes = File.ReadAllBytes( path );
99 return bytesToVector3List( bytes );
100 #endif
101 }
102
103
104 /// <summary>
105 /// helper to get a node list from an asset created with the visual editor
106 /// </summary>
107 public static List<Vector3> bytesToVector3List( byte[] bytes )
108 {
109 var vecs = new List<Vector3>();
110 for( var i = 0; i < bytes.Length; i += 12 )
111 {
112 var newVec = new Vector3( System.BitConverter.ToSingle( bytes, i ), System.BitConverter.ToSingle( bytes, i + 4 ), System.BitConverter.ToSingle( bytes, i + 8 ) );
113 vecs.Add( newVec );
114 }
115
116 return vecs;
117 }
118
119
120 /// <summary>
121 /// gets the last node. used to setup relative tweens
122 /// </summary>
123 public Vector3 getLastNode()
124 {
125 return _solver.nodes[_solver.nodes.Count];
126 }
127
128
129 /// <summary>
130 /// responsible for calculating total length, segmentStartLocations and segmentDistances
131 /// </summary>
132 public void buildPath()
133 {
134 _solver.buildPath();
135 }
136
137
138 /// <summary>
139 /// directly gets the point for the current spline type with no lookup table to adjust for constant speed
140 /// </summary>
141 private Vector3 getPoint( float t )
142 {
143 return _solver.getPoint( t );
144 }
145
146
147 /// <summary>
148 /// returns the point that corresponds to the given t where t >= 0 and t <= 1 making sure that the
149 /// path is traversed at a constant speed.
150 /// </summary>
151 public Vector3 getPointOnPath( float t )
152 {
153 // if the path is closed, we will allow t to wrap. if is not we need to clamp t
154 if( t < 0 || t > 1 )
155 {
156 if( isClosed )
157 {
158 if( t < 0 )
159 t += 1;
160 else
161 t -= 1;
162 }
163 else
164 {
165 t = Mathf.Clamp01( t );
166 }
167 }
168
169 return _solver.getPointOnPath( t );
170 }
171
172
173 /// <summary>
174 /// closes the path adding a new node at the end that is equal to the start node if it isn't already equal
175 /// </summary>
176 public void closePath()
177 {
178 // dont let this get closed twice!
179 if( isClosed )
180 return;
181
182 isClosed = true;
183 _solver.closePath();
184 }
185
186
187 /// <summary>
188 /// reverses the order of the nodes
189 /// </summary>
190 public void reverseNodes()
191 {
192 if( !_isReversed )
193 {
194 _solver.reverseNodes();
195 _isReversed = true;
196 }
197 }
198
199
200 /// <summary>
201 /// unreverses the order of the nodes if they were reversed
202 /// </summary>
203 public void unreverseNodes()
204 {
205 if( _isReversed )
206 {
207 _solver.reverseNodes();
208 _isReversed = false;
209 }
210 }
211
212
213 public void drawGizmos( float resolution )
214 {
215 _solver.drawGizmos();
216
217 var previousPoint = _solver.getPoint( 0 );
218
219 resolution *= _solver.nodes.Count;
220 for( var i = 1; i <= resolution; i++ )
221 {
222 var t = (float)i / resolution;
223 var currentPoint = _solver.getPoint( t );
224 Gizmos.DrawLine( currentPoint, previousPoint );
225 previousPoint = currentPoint;
226 }
227 }
228
229
230 /// <summary>
231 /// helper for drawing gizmos in the editor
232 /// </summary>
233 public static void drawGizmos( Vector3[] path, float resolution = 50 )
234 {
235 // horribly inefficient but it only runs in the editor
236 var spline = new GoSpline( path );
237 spline.drawGizmos( resolution );
238 }
239
240 }